package com.neuedu.weishi.util;

import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;

import java.time.Instant;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * 签名工具
 *
 * @author wzr
 */
public class SignUtils {

    /**
     * 签名随机key,服务器重启后,客户端令牌失效,需要重新登录
     */
    private static String KEY = RandomCodeUtils.bulidRepeatCodes(32);
    /**
     * 签名头部参数,根据业务需求进行修改
     * 注意:如果头部参数修改,需要修改客户端的签名算法
     */
    private static String[] HEAD_NAMES = new String[]{"host", "user-agent", "sec-ch-ua", /*"referer"*/};

    /**
     * 获得签名token
     *
     * @param hasRandomStr 是否包含随机字符串 true:包含;false:不包含
     * @param userId       :用户ID(int类型的ID需要转成String类型)
     * @param request      :http请求
     * @return
     */
    public static String getToken(boolean hasRandomStr, String userId, HttpServletRequest request) {
        //获取请求头部值
        Map<String, String> treeMap = new TreeMap<String, String>();
        for (String headName : HEAD_NAMES) {
            String headValue = request.getHeader(headName);
            headValue = StrUtil.isEmpty(headValue) ? "none" : headValue;
            treeMap.put(headName, headValue);
            System.out.println(headName + ":" + headValue);
        }
        //获取客户端IP地址
        String ip = IpUtils.getIpAddr(request);
        treeMap.put("clientIp", ip);
        treeMap.put("userId", userId);
        //客户端MAC地址
        Iterator<String> keyIter = treeMap.keySet().iterator();
        StringBuffer strABuf = new StringBuffer();
        while (keyIter.hasNext()) {
            String key = keyIter.next();
            strABuf.append(key);
            strABuf.append('=');
            String value = treeMap.get(key);
            strABuf.append(value);
            strABuf.append('&');
        }
        String stringA = strABuf.toString();
        String stringSignTemp = stringA + "key=" + KEY;
        String token = EncryptUtils.getMD5(stringSignTemp).toUpperCase();
        if (hasRandomStr) {
            token += getNonceStr();
            token = DES.encode(KEY, token + RandomCodeUtils.bulidRepeatCodes(8).toUpperCase());
        }
        return token;
    }

    /**
     * 解密token,去除随机字符串
     *
     * @param token
     * @return
     */
    public static String removeRandomStr(String token) {
        return DES.decode(KEY, token).substring(0, 32);
    }

    /**
     * 获取随机字符串
     *
     * @return
     */
    public static String getNonceStr() {
        String randomStr = RandomCodeUtils.bulidRepeatCodes(32)
                + String.valueOf(System.currentTimeMillis());
        return EncryptUtils.getMD5(randomStr).toUpperCase();
    }

    /**
     * 标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数(10位数字) 对于毫秒进行四舍五入
     *
     * @return
     */
    public static long getNowSeconds() {
        long time = System.currentTimeMillis();
        return Math.round(time / 1000.0);
    }

    /**
     * 失效时间
     *
     * @param min :交易失效时间(单位分钟,必须大于5分钟)
     * @return
     */
    public static long getTimeExpire(int min) {
        if (min < 5) {
            throw new IllegalArgumentException("最短失效时间间隔必须大于5分钟");
        }
        return getNowSeconds() + min * 60;
    }

    /**
     * 新增：获取当前系统时间（UTC），精确到纳秒
     * 返回自1970-01-01T00:00:00Z（ epoch 时间）以来的总纳秒数
     *
     * @return 纳秒级时间戳（19位数字，格式：秒数*1e9 + 纳秒部分）
     */
    public static long getNowNanos() {
        Instant instant = Instant.now(); // 获取当前瞬时时间（UTC）
        // 计算总纳秒数：秒数*1e9 + 纳秒部分（0-999,999,999）
        return instant.getEpochSecond() * 1_000_000_000L + instant.getNano();
    }

}

